local SkillShow = class("SkillShow")
local FightHelper = require("gameLogic.fight.FightHelper")
local GameUtils = require("utils.GameUtils")
local FightConst = require("const.FightConst")

function SkillShow:ctor(manager)
    self._manager = manager
end

function SkillShow:setEndCallback(callback)
    self._callback = callback
end

function SkillShow:setBeAttackCallback(beAttackCallback)
    self._beAttackAfter = beAttackCallback
end

function SkillShow:show(config, actor, targetActors)
    if self._sequence then
        self._sequence:destroy()
        self._sequence = nil
    end
    self._sequence = SkillShaowParser.parse(config, actor, targetActors)
end

function SkillShow:update()
    if not self._sequence then
        return
    end
    if not self._sequence:isDone() then
        self._sequence:tick()
    else
        self._sequence:destroy()
        self._sequence = nil
    end
end

function SkillShow:_goDone()
    self._sequence = nil
    if self._callback then
        self._callback()
        self._callback = nil
    end
end

function SkillShow:beAttack(targetActors)
    local AttributeConst = require("const.AttributeConst")
    for i = 1, #targetActors do
        local tarActor = targetActors[i].actor
        local hurt = targetActors[i].hurt
        local param = FightHelper.generateHurtFly(tarActor, targetActors[i].hurt)
        G_SignalManager:dispatch(SignalConst.EVENT_FIGHT_HURT_TEXT, param)
        tarActor:setBloodValue(hurt.blood, hurt.maxBlood)
        if hurt.element ~= AttributeConst.ELEMENT_TREATMENT then
            tarActor:playAction("Hurt")
        end
    end
end

function SkillShow:_SkillMove(actor, targetActors)
    local sequence = DOTween.Sequence()
    local nearActor = FightHelper.getNearActor(actor, targetActors)
    local myPos = actor.transform.position
    local tarPos = nearActor.transform.position
    tarPos.z = tarPos.z + 1 * FightConst.Z_RATIO[actor:getCamp()]
    local callMove = function()
        actor:setMoving(true)
    end
    local move = actor.transform:DOMove(tarPos, 0.5)
    local callAttackBefore = function()
    end
    local callAttack = function()
        actor:setMoving(false)
        self:_effectPlay(targetActors)
        actor:playAction(self._config.action)
    end
    local callBeAttack = function()
        self:beAttack(targetActors)
    end
    local callAttackAfter = function()
        if self._beAttackAfter then
            self._beAttackAfter()
        end
    end
    local moveBack = actor.transform:DOMove(myPos, 0.5)
    local callIdle = function()
        actor:setMoving(false)
    end
    local atkTime = actor:getAnimationLength(self._config.action)
    sequence:AppendCallback(callMove)
    sequence:Append(move)
    sequence:AppendCallback(callAttackBefore)
    sequence:AppendCallback(callAttack)
    sequence:AppendInterval(0.3)
    sequence:AppendCallback(callBeAttack)
    sequence:AppendInterval(atkTime - 0.3)
    sequence:AppendCallback(callAttackAfter)
    if self._config.effect_time > atkTime then
        sequence:AppendInterval(self._config.effect_time - atkTime)
    end
    sequence:AppendInterval(0.1)
    sequence:AppendCallback(
        function()
            actor:setMoving(true)
        end
    )
    sequence:Append(moveBack)
    sequence:AppendCallback(
        function()
            actor:setMoving(false)
        end
    )
    sequence:AppendCallback(handler(self, self._goDone))
    self._sequence = sequence
end

function SkillShow:_SkillInPlace(actor, targetActors)
    local callAttackBefore = function()
    end
    local callAttack = function()
        self:_effectPlay(targetActors)
        actor:playAction(self._config.action)
    end
    local callBeAttack = function()
        self:beAttack(targetActors)
    end
    local callAttackAfter = function()
    end
    local atkTime = actor:getAnimationLength(self._config.action)
    local sequence = DOTween.Sequence()
    sequence:AppendCallback(callAttackBefore)
    sequence:AppendCallback(callAttack)
    sequence:AppendInterval(0.3)
    sequence:AppendCallback(callBeAttack)
    sequence:AppendInterval(atkTime - 0.3)
    sequence:AppendCallback(callAttackAfter)
    if self._config.effect_time > atkTime then
        sequence:AppendInterval(self._config.effect_time - atkTime)
    end
    sequence:AppendInterval(0.2)
    sequence:AppendCallback(handler(self, self._goDone))
    self._sequence = sequence
end

function SkillShow:_SkillMoveCenter(actor, targetActors)
    local myPos = actor.transform.position
    local Vector3 = require("utils.Vector3")
    local targetPos = actor:getManager():getCenterPos()
    local move = actor.transform:DOMove(targetPos, 0.5)
    local callMove = function()
        -- actor:setBloodVisible(false)
        actor:setMoving(true)
    end
    local callAttackBefore = function()
    end
    local callAttack = function()
        actor:setMoving(false)
        self:_effectPlay(targetActors)
        actor:playAction(self._config.action)
    end
    local callBeAttack = function()
        self:beAttack(targetActors)
    end
    local callAttackAfter = function()
    end
    local moveBack = actor.transform:DOMove(myPos, 0.5)
    local atkTime = actor:getAnimationLength(self._config.action)
    local sequence = DOTween.Sequence()
    sequence:AppendCallback(callMove)
    sequence:Append(move)
    sequence:AppendCallback(callAttackBefore)
    sequence:AppendCallback(callAttack)
    sequence:AppendInterval(0.3)
    sequence:AppendCallback(callBeAttack)
    sequence:AppendInterval(atkTime - 0.3)
    sequence:AppendCallback(callAttackAfter)
    if self._config.effect_time > atkTime then
        sequence:AppendInterval(self._config.effect_time - atkTime)
    end
    sequence:AppendInterval(0.1)
    sequence:AppendCallback(
        function()
            actor:setMoving(true)
        end
    )
    sequence:Append(moveBack)
    sequence:AppendCallback(
        function()
            actor:setMoving(false)
        end
    )
    sequence:AppendCallback(handler(self, self._goDone))
    self._sequence = sequence
end

-- 技能特效类型 begin
function SkillShow:_effectPlay(targets)
    local targetActors = {}
    for i = 1, #targets do
        table.insert(targetActors, targets[i].actor)
    end
    local typeName = self._config.effect_type
    local effectFunc = self["_effect_" .. typeName]
    if effectFunc and type(effectFunc) == "function" then
        effectFunc(self, targetActors)
    end
end

function SkillShow:_effect_single(targets)
    local FightHelper = require("gameLogic.fight.FightHelper")
    local targetPos = FightHelper.getActorCenterPos(targets)
    self:_playEffect(targetPos)
end

function SkillShow:_effect_multiple(targets)
    for i, v in ipairs(targets) do
        local effectPosition = v.transform.position
        effectPosition.z = effectPosition.z + 0.3
        self:_playEffect(effectPosition)
    end
end

function SkillShow:_playEffect(effectPosition)
    local effectName = self._config.effect
    if effectName == "none" then
        return
    end

    local object = G_ResourceManager:loadEffect(effectName)
    local gameObject = GameUtils.instantiate(object)
    gameObject.transform.position = effectPosition
    local sequence = DOTween.Sequence()
    sequence:AppendInterval(self._config.effect_time)
    sequence:AppendCallback(
        function()
            GameUtils.destroy(gameObject)
        end
    )
    self._sequence = sequence
end
-- 技能特效类型 end

function SkillShow:destroy()
    DOTween.KillAll()
end

return SkillShow
